package com.xyf.sys.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fdd.api.conf.FddApiConfig;
import com.fdd.api.model.*;
import com.fdd.api.util.GZipUtil;
import com.fdd.api.util.SignUtil;
import com.xyf.sys.config.CustomException;
import com.xyf.sys.domain.PrintTask;
import com.xyf.sys.domain.UserPrinter;
import com.xyf.sys.mapper.PrintTaskMapper;
import com.xyf.sys.mapper.UserPrinterMapper;
import com.xyf.sys.service.IUserPrinterService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @Author R-H
 * @Date 2024/2/241908
 * @Description
 */
@Slf4j
@Service
public class UserPrinterServiceImpl implements IUserPrinterService {

    private FddApiConfig fddApiConfig;
    private UserPrinterServiceImpl(){
        fddApiConfig = new FddApiConfig();
        fddApiConfig.setAppId("97aea4b59fd1487388481862e75cb3a9");
        fddApiConfig.setAppSecret("ec67720904f84f45b3aa2b7ef7dc421e");
    }
    @Autowired
    private UserPrinterMapper userPrinterMapper;
    @Autowired
    private PrintTaskMapper printTaskMapper;

    @Override
    public UserPrinter get(Long id) {
        return userPrinterMapper.selectByPrimaryKey(id);
    }

    @Override
    public List<UserPrinter> getList(String openid) {
        return userPrinterMapper.selectPrinterList(openid);
    }


    @Override
    public int remove(Long id) {
        UserPrinter printer = userPrinterMapper.selectByPrimaryKey(id);
        printer.setStatus("1");
        printer.setDelFlag("1");
        printer.setUpdateTime(new Date());
        printer.setLastUpdateTime(new Date());
        return userPrinterMapper.updateByPrimaryKey(printer);
    }

    @Override
    public void removeAll(String userId) {
        List<UserPrinter> list = this.getList(userId);
        for (UserPrinter printer : list) {
            printer.setStatus("1");
            printer.setDelFlag("1");
            printer.setUpdateTime(new Date());
            printer.setUpdateBy(userId);
            this.userPrinterMapper.updateByPrimaryKey(printer);
        }
    }

    @Override
    public UserPrinter save(UserPrinter printer) {
        if (printer.getId() == null) {
            if (!CollectionUtils.isEmpty(this.find(printer.getUserId(), printer.getSiid()))) {
                throw new CustomException("您已经添加过该打印机,请勿重复添加");
            }
            printer.setStatus("0");
            printer.setDelFlag("0");
            printer.setCreateTime(new Date());
            printer.setLastUpdateTime(new Date());
            printer.setCreateBy(printer.getUserId());
            userPrinterMapper.insert(printer);
            return printer;
        } else {
            UserPrinter userPrinter = userPrinterMapper.selectByPrimaryKey(printer.getId());
            userPrinter.setName(printer.getName());
            userPrinter.setSiid(printer.getSiid());
            userPrinter.setDelFlag(printer.getDirection());
            userPrinter.setUpdateTime(new Date());
            userPrinter.setLastUpdateTime(new Date());
            userPrinter.setUpdateBy(printer.getUserId());
            userPrinterMapper.updateByPrimaryKey(userPrinter);
            return userPrinter;
        }
    }

    @Override
    public List<UserPrinter> find(String userId, String siid) {
        return userPrinterMapper.selectBySiid(userId, siid);
    }

    @Override
    public Object printCaptcha(String printerId, String userId) {
        CaptchaReq captchaReq = new CaptchaReq(printerId);
        String bizData = JSONUtil.toJsonStr(captchaReq);
        String nonce = System.currentTimeMillis() + "";
        String sign = SignUtil.makeSign(bizData + nonce, fddApiConfig.getAppSecret());
        OpenApiRequest pubApiRequest = new OpenApiRequest();
        pubApiRequest.setAppId(fddApiConfig.getAppId());
        pubApiRequest.setBizData(bizData);
        pubApiRequest.setNonce(nonce);
        pubApiRequest.setTimestamp(nonce);
        Map<String, String> header = new HashMap<>();
        header.put("sign", sign);
        String postData = JSONUtil.toJsonStr(pubApiRequest);
        String result = HttpRequest.post(FddApiConfig.URL_CAPTCHA)
                .headerMap(header, false)
                .body(postData)
                .timeout(10000)
                .execute()
                .body();
        BaseApiResponse captchaResp = JSONUtil.toBean(result, BaseApiResponse.class);
        System.out.println("captcha result: " + captchaResp.toString());
        log.info("print captcha result {}" , JSONObject.toJSONString(captchaResp));
        if (captchaResp.getCode() != 200) {
            throw new CustomException(captchaResp.getDesc());
        }
        return captchaResp.getData();
    }


    @Override
    public Object printerBind(String printerId, String captcha, String userId, Long deptId) {
        BindReq bindReq = new BindReq(printerId, captcha);
        String bizData = JSONUtil.toJsonStr(bindReq);
        String nonce = System.currentTimeMillis() + "";
        String sign = SignUtil.makeSign(bizData + nonce, fddApiConfig.getAppSecret());
        OpenApiRequest pubApiRequest = new OpenApiRequest();
        pubApiRequest.setAppId(fddApiConfig.getAppId());
        pubApiRequest.setBizData(bizData);
        pubApiRequest.setNonce(nonce);
        pubApiRequest.setTimestamp(nonce );
        Map<String, String> header = new HashMap<>();
        header.put("sign", sign);
        String postData = JSONUtil.toJsonStr(pubApiRequest);
        String result = HttpRequest.post(FddApiConfig.URL_BIND)
                .headerMap(header, false)
                .body(postData)
                .timeout(10000)
                .execute()
                .body();
        BaseApiResponse captchaResp = JSONUtil.toBean(result, BaseApiResponse.class);
        System.out.println("captcha result: " + result);
        log.info("print bind result {}" , JSONObject.toJSONString(captchaResp));
        System.out.println("captcha result: " + captchaResp.toString());
        if (captchaResp.getCode() == 200){
            String printerCode = captchaResp.getData().toString();
            List<UserPrinter> printers = userPrinterMapper.selectBySiid(userId, printerCode);
            if (!CollectionUtils.isEmpty(printers)){
                for (UserPrinter printer : printers) {
                    printer.setDelFlag("1");
                    printer.setUpdateTime(new Date());
                    userPrinterMapper.updateByPrimaryKeySelective(printer);
                }
            }
            UserPrinter userPrinter = new UserPrinter();
            userPrinter.setUserId(userId);
            userPrinter.setDeptId(deptId);
            userPrinter.setSiid(printerId);
            userPrinter.setShareCode(printerCode);
            userPrinter.setType(2);
            userPrinter.setStatus("0");
            userPrinter.setDelFlag("0");
            userPrinter.setCreateTime(new Date());
            userPrinter.setCreateBy(userId);
            return userPrinterMapper.insert(userPrinter);
        }
        throw new CustomException(JSONObject.toJSONString(captchaResp));
    }

    @Override
    public Object printerUnBind(Long id, String userId) {
        UserPrinter userPrinter = userPrinterMapper.selectByPrimaryKey(id);
        userPrinter.setDelFlag("1");
        userPrinter.setStatus("1");
        return userPrinterMapper.updateByPrimaryKeySelective(userPrinter);
    }

    @Override
    public Object cloudPrint(Long id, String waybillPrinterData, String userId) {
        UserPrinter userPrinter = userPrinterMapper.selectByPrimaryKey(id);
        PrintReq req = new PrintReq(userPrinter.getSiid(), userPrinter.getShareCode());
        List<PrintDataDto> printDataDtos = new ArrayList<>();
        PrintDataDto dataDto = new PrintDataDto();
        dataDto.setPrintType("tspl");
        long taskId = IdUtil.getSnowflakeNextId();
        dataDto.setId(String.valueOf(taskId));
        dataDto.setWaybillPrinterData(GZipUtil.gZip(waybillPrinterData, "gbk"));
        printDataDtos.add(dataDto);
        req.setPrintData(printDataDtos);
        req.setShareCode(userPrinter.getShareCode());
        req.setPrinterId(userPrinter.getSiid());
        String bizData = JSONUtil.toJsonStr(req);
        String nonce = System.currentTimeMillis() + "";
        String sign = SignUtil.makeSign(bizData + nonce, fddApiConfig.getAppSecret());
        OpenApiRequest pubApiRequest = new OpenApiRequest();
        pubApiRequest.setAppId(fddApiConfig.getAppId());
        pubApiRequest.setBizData(bizData);
        pubApiRequest.setNonce(nonce);
        pubApiRequest.setTimestamp(nonce);
        Map<String, String> header = new HashMap<>();
        header.put("sign", sign);
        String postData = JSONUtil.toJsonStr(pubApiRequest);
        String result = HttpRequest.post(FddApiConfig.URL_PRINT)
                .headerMap(header, false)
                .body(postData)
                .timeout(10000)
                .execute()
                .body();
        log.info("print result {}" , result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject.getInteger("code") == 200){
            PrintResp resp = JSONUtil.toBean(jsonObject.getString("data"), PrintResp.class);
            log.info("print resp {}" , JSONObject.toJSONString(resp));
            List<PrintTask> taskList = new ArrayList<>();
            for (PrintResultDto printResultDto : resp.getPrintResultList()) {
                PrintTask printTask = new PrintTask();
                printTask.setUserId(userId);
                printTask.setPrintTaskId(printResultDto.getPrintTaskId());
                printTask.setPrinterId(userPrinter.getId().toString());
                printTask.setMessage(printResultDto.getFailReason());
                printTask.setStatus(printResultDto.getResult() == null || !printResultDto.getResult() ? "0" : "1");
                printTask.setDelFlag("0");
                printTask.setCreateTime(new Date());
                printTask.setCreateBy(userId);
                printTask.setRemark(jsonObject.getString("data"));
                printTaskMapper.insertSelective(printTask);
                taskList.add(printTask);
            }
            return taskList;
        } else {
            throw new CustomException("打印失败：" + jsonObject.getString("desc"));
        }
    }

    @Override
    public boolean printCallback(Map<String, Object> body) {
        log.info("print callback {}", JSONObject.toJSONString(body));
        String bizData = body.get("bizData").toString();
        JSONObject jsonObject = JSONObject.parseObject(bizData);
        String taskId = jsonObject.getString("taskId");
        String status = jsonObject.getString("status");
        String printerId = jsonObject.getString("machineCode");
        PrintTask printTask = printTaskMapper.selectByPrintTaskId(taskId);
        printTask.setStatus(status);
        printTask.setMessage(jsonObject.getString("reason"));
        printTask.setRemark(JSONObject.toJSONString(body));
        printTask.setUpdateTime(new Date());
        return printTaskMapper.updateByPrimaryKeySelective(printTask) > 0;
    }
}
